﻿using AutoMapper;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WCS_Entity.Dto.UserDto;
using WCS_Entity.User;
using WCS_Repository.Interface;
using WCS_Service.Interface;

namespace WCS_Service.Services
{
    /// <summary>
    /// 角色管理服务
    /// </summary>
    public class RoleService : BaseService<RulesEntity>, IRoleService
    {
        private readonly IRuleRepository _ruleRepository;
        private readonly IMenuRepository _menuRepository;
        private readonly IMapper _mapper;
        public RoleService(IMapper mapper,
                           IMenuRepository menuRepository,
                           IRuleRepository ruleRepository) 
        {
            _mapper = mapper;
            _menuRepository = menuRepository;
            _ruleRepository = ruleRepository;
        }

        public async Task<RuleDto> CreateRuleAsync(CreateRuleDto dto)
        {
            string menuIds = string.Join(",", dto.MenuIds);
            var flag = await _ruleRepository.ExistsAsync(r => r.ruleName == dto.ruleName || r.menuIds == menuIds);
            if (flag)
            {
                Log.Error($"创建角色{dto.ruleName}已经存在,或对应权限已经存在!");
                return null;
            }

            var rule = _mapper.Map<RulesEntity>(dto);
            rule.createTime = DateTime.Now;
            rule.menuIds = string.Join(",", dto.MenuIds);
            await _ruleRepository.InsertAsync(rule);

            var result = _mapper.Map<RuleDto>(rule);
            var menuIDs = rule.menuIds.Split(',');
            var menuInfos = await _menuRepository.QueryByIDsAsync(menuIDs);
            if (menuInfos is not null && menuInfos.Any())
            {
                result.MenuName = menuInfos.Select(m => m.name).ToList();
            }
            return result;
        }

        public async Task<bool> DeleteRuleAsync(int ruleId)
        {
            return await _ruleRepository.DeleteByIdAsync(ruleId);
        }

        public async Task<List<RuleDto>> QueryAllRuleAsync()
        {
            List<RuleDto> result = new List<RuleDto>();
            Expression<Func<RulesEntity, object>> orderEx = p => p.createTime;
            var rules = await _ruleRepository.QueryPageAsync(null, orderEx, OrderByType.Desc, 1,10);
            if (rules is null || !rules.Any())
            {
                Log.Error("查找所有角色信息失败");
                return null;
            }
            List<Task<RuleDto>> ruleDtos = new List<Task<RuleDto>>();
            foreach (var rule in rules) 
            {
                ruleDtos.Add(GetRuleDtoAsync(rule));
            }
            await Task.WhenAny(ruleDtos);
            result = ruleDtos.Select(r => r.Result).ToList();
            return result;
        }

        public async Task<RuleDto> QueryRuleAsync(int ruleId)
        {
            var ruleEntity = await _ruleRepository.QueryByIdAsync(ruleId);
            if (ruleEntity is null)
            {
                Log.Error($"查询角色{ruleId}信息不存在");
                return null;
            }
            var result = _mapper.Map<RuleDto>(ruleEntity);
            var menuIds = ruleEntity.menuIds.Split(",");
            var menuInfos = await _menuRepository.QueryByIDsAsync(menuIds);
            if (menuInfos is not null || menuInfos.Any())
            {
                result.MenuName = menuInfos.Select(m => m.name).ToList();
            }
            return result;
        }

        public async Task<RuleDto> UpdateRuleAsync(UpdateRuleDto dto)
        {
            var ruleEntity = await _ruleRepository.QueryByIdAsync(dto.Id);
            if (ruleEntity is null)
            {
                Log.Error($"更新角色{dto.Id}信息不存在");
                return null;
            }
            if (ruleEntity.ruleName != dto.Name)
            {
                ruleEntity.ruleName = dto.Name;
            }
            if (ruleEntity.status != dto.status)
            { 
                ruleEntity.status = dto.status;
            }
            var menuIds = string.Join(",", dto.MenuIds);
            if (ruleEntity.menuIds != menuIds)
            {
                ruleEntity.menuIds = menuIds;
            }
            ruleEntity.updataTime = DateTime.Now;

            await _ruleRepository.UpdateAsync(ruleEntity);
            var result = _mapper.Map<RuleDto>(ruleEntity);
            var menuIDs = ruleEntity.menuIds.Split(',');
            var menuInfos = await _menuRepository.QueryByIDsAsync(menuIDs);
            if (menuInfos is not null && menuInfos.Any())
            {
                result.MenuName = menuInfos.Select(m => m.name).ToList();
            }
            return result;
        }

        #region Private
        private async Task<RuleDto> GetRuleDtoAsync(RulesEntity entity)
        {
            var dto = _mapper.Map<RuleDto>(entity);
            var ids = entity.menuIds.Split(',');
            var menuInfos = await _menuRepository.QueryByIDsAsync(ids);
            if (menuInfos is not null && menuInfos.Any())
            {
                dto.MenuName =  menuInfos.Select(m => m.name).ToList();
            }
            return dto;
        }
        #endregion
    }
}
